package com.epoint.netty.rpc.client;

import com.epoint.netty.chat.protocol.MessageCodecSharable;
import com.epoint.netty.rpc.common.RpcRequestMessage;
import com.epoint.netty.rpc.server.User;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public class Client_V2 {

    private static volatile Channel channel = null;
    private static Object lock = new Object();

    public static Channel getChannel(){
        if(channel == null){
            synchronized (lock){
                if(channel == null){
                    initChannel();
                }
            }
        }
        return channel;
    }

    private static void initChannel() {
        NioEventLoopGroup eventExecutors = new NioEventLoopGroup();
        MessageCodecSharable messageCodecSharable = new MessageCodecSharable();
        try {
            channel = new Bootstrap()
                    .group(eventExecutors)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<Channel>() {
                        @Override
                        protected void initChannel(Channel ch) {
                            ch.pipeline().addLast(new LoggingHandler(LogLevel.DEBUG));
                            ch.pipeline().addLast(messageCodecSharable);
                        }
                    })
                    .connect("localhost", 8080).sync().channel();

            // TODO 这里有个小暗坑，我一般喜欢用异步future的方式去获取Channel，但是future是异步的，说明此时Channel还没有呢，我就直接返回，是不对的，
            //  future配合回调函数用没问题，但是串行的去用就不对了
            // 配置关闭事件
            ChannelFuture channelFuture = channel.closeFuture();
            channelFuture.addListener((ChannelFutureListener) channelFuture1 -> {
                eventExecutors.shutdownGracefully();
            });

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) throws InterruptedException {
        RpcRequestMessage msg = new RpcRequestMessage(1, "com.epoint.netty.rpc.server.impl.UserServiceImpl",
                "getUserByName", User.class, new Class[]{String.class}, new Object[]{"纪宽豪"});
        getChannel().writeAndFlush(msg);
    }
}
